package org.orbis.structure;

import java.util.Arrays;

/** This class implements list, which dedicates to store long-size native value.
 * You can add, modify value, and delete.<br>
 * Thread safe: operations in this class is assured to be thread safe.
 * 
 * @author Yusuke FUJISAKA */
public class BlockingLongList{
	private long[] values;
	private int size;
	private double extendFilling;

	public BlockingLongList(int initial, double filling){
		if(initial < 0) throw new IllegalArgumentException("Negative initial value");
		if(filling < 0 || filling > 1) throw new IllegalArgumentException("Illegal filling value" + filling);
		this.values = new long[initial];
		this.extendFilling = filling;
	}

	public BlockingLongList(){
		this(10, 0.75);
	}

	private synchronized void extend(){
		int newSize = (int)(values.length * 3 / 2 + 1);

		values = Arrays.copyOf(values, newSize);
	}

	public synchronized void add(long val){
		values[size] = val;
		size++;
		if(size >= values.length * extendFilling) extend();
	}

	public synchronized void add(int index, long val){
		if(index < 0) index = 0;
		if(index >= size) add(val);
		for(int i = size - 1; i >= index; i--){
			values[i + 1] = values[i];
		}
		values[index] = val;
		size++;
		if(size >= values.length * extendFilling) extend();
	}

	public synchronized long get(int index){
		if(index < 0)
			throw new IllegalArgumentException(new StringBuffer("Out of range, negative value.").toString());
		if(index >= size)
			throw new IllegalArgumentException(new StringBuffer("Out of range. ").append(index)
				.append(" in ").append(size).toString());
		return values[index];
	}

	public synchronized void removeByIndex(int index){
		if(index < 0 || index >= size) return;
		for(int i = index + 1; i < size; i++)
			values[i - 1] = values[i];

		size--;
	}

	public synchronized void removeByValue(long value){
		for(int i = 0; i < size; i++){
			if(value == values[i]){
				for(int j = i + 1; j < size; j++)
					values[j - 1] = values[j];

				size--;
			}
		}
	}

	public synchronized void modify(int index, long value){
		if(index < 0 || index >= size) return;

		values[index] = value;
	}

	public synchronized int size(){
		return size;
	}

	public synchronized boolean contains(long value){
		for(int i = 0; i < size; i++){
			if(values[i] == value) return true;
		}
		return false;
	}

	public synchronized int indexOf(long value){
		for(int i = 0; i < size; i++){
			if(values[i] == value) return i;
		}
		return -1;
	}

	public long[] toArray(){
		return Arrays.copyOf(values, size);
	}
}
